import numpy as np
import pandas as pd
from datetime import datetime, timedelta
from typing import Optional, Union, Callable


def safe_cast(obj: Optional[Union[int, float]], cast: Callable) -> Optional[Union[int, float]]:
    return cast(obj) if obj is not None else obj


def clean_space(s: str) -> str:
    i, j = 0, len(s)
    symbols = ['\s', ' ', '\t', '\n']
    while s[i] in symbols:
        i += 1
    while s[j - 1] in symbols:
        j -= 1
    return s[i:j]


def get_date(form: str = '%d.%m.%Y', dt: bool = True) -> str:
    now = datetime.now()
    dayofweek = datetime.isoweekday(now)

    delta = 1
    if dayofweek >= 5:
        delta = 8 - dayofweek

    result = (now + timedelta(days=delta)).strftime(form)
    if dt:
        result = pd.to_datetime(result)
    return result


def np_converter(obj):
    if isinstance(obj, np.integer):
        return int(obj)
    elif isinstance(obj, np.floating):
        return float(obj)
    elif isinstance(obj, np.ndarray):
        return obj.tolist()
    elif isinstance(obj, datetime):
        return obj.__str__()


def time_from_string_to_int(s):
    time_list = s.split(':')
    hours = int(time_list[0])
    minutes = int(time_list[1])
    return hours * 60 + minutes


def time_from_int_to_string(n):
    hours = n // 60
    minutes = n % 60
    s = ('0' + str(hours))[-2:] + ':' + ('0' + str(minutes))[-2:]
    return s
